//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
/*
 * memsetup-monahans.S :memory setup for Manzano/Monahans architectures
 *
 * Copyright (c) 2003, Intel Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 */

#include <arch.h>

/* The potential issue is that the macro resets the value of OSCR register. -stanley */
.macro wait time
        ldr             r2, =OSCR
        mov             r3, #0
        str             r3, [r2]
0:
        ldr             r3, [r2]
        cmp             r3, \time
        bls             0b
.endm

.macro cpwait reg
	mrc  p15,0,\reg,c2,c0,0
	mov  \reg,\reg
	sub  pc,pc,#4
.endm

.text

.globl memsetup
memsetup:

	mov 	r10, lr

#if 0 /* Did it just after reset. -SC */
	/* tebrandt - allow coprocessor c6 access */
	ldr		r0, =0x0040
	mcr		p15, 0, r0, c15, c1, 0
	cpwait r0
#endif

@********************************************************************
@ Initlialize Memory Controller
@ The sequence below is based on the recommended init steps detailed
@ in the EAS, chapter 5.
@
@ pause for 200 uSecs- allow internal clocks to settle
@ *Note: only need this if hard reset... doing it anyway for now
@
@ ---- Wait 200 usec

	wait #768

@****************************************************************************
@  Step 1
@

@ configure the MEMCLKCFG register
        ldr             r1, =MEMCLKCFG
        ldr             r2, =0x00010001
        str             r2, [r1]             @ WRITE
        ldr             r2, [r1]             @ DELAY UNTIL WRITTEN

@ set CSADRCFG[0] to data flash SRAM mode
	ldr             r1, =CSADRCFG0
	ldr             r2, =0x00320809
	str             r2, [r1]             @ WRITE
	ldr             r2, [r1]             @ DELAY UNTIL WRITTEN

@ set CSADRCFG[1] to data flash SRAM mode
	ldr             r1, =CSADRCFG1
	ldr             r2, =0x00320809
	str             r2, [r1]             @ WRITE
	ldr             r2, [r1]             @ DELAY UNTIL WRITTEN

@ set MSC 0 register for SRAM memory
        ldr             r1, =MSC0
        ldr             r2, =0x11191119
        str             r2, [r1]             @ WRITE
        ldr             r2, [r1]             @ DELAY UNTIL WRITTEN

@ set CSADRCFG[2] to data flash SRAM mode
	ldr             r1, =CSADRCFG2
	ldr             r2, =0x00320809
	str             r2, [r1]             @ WRITE
	ldr             r2, [r1]             @ DELAY UNTIL WRITTEN

@ set CSADRCFG[3] to VLIO mode
        ldr             r1, =CSADRCFG3
        ldr             r2, =0x0032080B
        str             r2, [r1]             @ WRITE
        ldr             r2, [r1]             @ DELAY UNTIL WRITTEN

@ set MSC 1 register for VLIO memory
        ldr             r1, =MSC1
        ldr             r2, =0x123C1119
        str             r2, [r1]             @ WRITE
        ldr             r2, [r1]             @ DELAY UNTIL WRITTEN

#if 0
	/* This does not work in Zylonite. -SC */
	ldr		r0, =0x15fffff0
	ldr		r1, =0xb10b
	str		r1, [r0]
	str		r1, [r0, #4]
#endif

	@ Configure ACCR Register
	ldr		r0, =ACCR		@ ACCR
	ldr		r1, =0x0180b108
	str		r1, [r0]
	ldr		r1, [r0]

	@ Configure MDCNFG Register
	ldr		r0, =MDCNFG		@ MDCNFG
	ldr		r1, =0x403
	str		r1, [r0]
	ldr		r1, [r0]

	@ Perform Resistive Compensation by configuring RCOMP register
	ldr		r1, =RCOMP		@ RCOMP
	ldr		r2, =0x000000ff
	str		r2, [r1]
	ldr		r2, [r1]

	@ Configure MDMRS Register for SDCS0
	ldr		r1, =MDMRS		@ MDMRS
	ldr		r2, =0x60000023
	ldr		r3, [r1]
	orr		r2, r2, r3
	str		r2, [r1]
	ldr		r2, [r1]

	@ Configure MDMRS Register for SDCS1
	ldr		r1, =MDMRS		@ MDMRS
	ldr		r2, =0xa0000023
	ldr		r3, [r1]
	orr		r2, r2, r3
	str		r2, [r1]
	ldr		r2, [r1]

	@ Configure MDREFR
	ldr		r1, =MDREFR		@ MDREFR
	ldr		r2, =0x00000006
	str		r2, [r1]
	ldr		r2, [r1]

	@ Configure EMPI
	ldr		r1, =EMPI		@ EMPI
	ldr		r2, =0x80000000
	str		r2, [r1]
	ldr		r2, [r1]

@@ DDR Read-Strobe Delay Calibration
	bl	ddr_calibration

	/* Here we assume the hardware calibration alwasy be successful. -SC */
	@ Set DMCEN bit	in MDCNFG Register
	ldr		r0, =MDCNFG		@ MDCNFG
	ldr		r1, [r0]
	orr		r1, r1, #0x40000000	@ enable SDRAM for Normal Access
	str		r1, [r0]

@@ scrub/init SDRAM if enabled/present
	ldr	r11, =0xa0000000 //RAM_BASE	// base address of SDRAM
	ldr	r12, =0x04000000 // size of memory to scrub
	mov	r8,r12		// save DRAM size
	mov	r0, #0		// scrub with 0x0000:0000
	mov	r1, #0
	mov	r2, #0
	mov	r3, #0
	mov	r4, #0
	mov	r5, #0
	mov	r6, #0
	mov	r7, #0
10: @@ fastScrubLoop
	subs	r12, r12, #32	// 32 bytes/line
	stmia	r11!, {r0-r7}
	beq	15f
	b	10b

15:
	/* Mask all interrupts */
	mov	r1, #0
	mcr	p6, 0, r1, c1, c0, 0	@ ICMR

	//Disable software and data breakpoints
	mov	r0, #0
	mcr	p15,0,r0,c14,c8,0  // ibcr0
	mcr	p15,0,r0,c14,c9,0  // ibcr1
	mcr	p15,0,r0,c14,c4,0  // dbcon

	//Enable all debug functionality
	mov	r0,#0x80000000
	mcr	p14,0,r0,c10,c0,0  // dcsr

ret:
	mov	pc, r10

@********************************************************************************
@ DDR calibration
@
@  This function is used to calibrate DQS delay lines.
@ Monahans supports three ways to do it. One is software
@ calibration. Two is hardware calibration. Three is hybrid
@ calibration.
@
@ TBD
@ -SC
ddr_calibration:

/*
	@ Case 1:	Write the correct delay value once
        @ Configure DDR_SCAL Register
	ldr             r0, =DDR_SCAL           @ DDR_SCAL
	ldr             r1, =0xaf2f2f2f
	str             r1, [r0]
	ldr             r1, [r0]
*/
/*	@ Case 2:	Software Calibration
	@ Write test pattern to memory
	ldr		r5, =0x0faf0faf         @ Data Pattern
	ldr		r4, =0xa0000000		@ DDR ram
	str		r5, [r4]

	mov		r1, =0x0		@ delay count
	mov		r6, =0x0
	mov		r7, =0x0
ddr_loop1:
	add		r1, r1, =0x1
	cmp		r1, =0xf
	ble		end_loop
	mov		r3, r1
	mov             r0, r1, lsl #30
	orr		r3, r3, r0
	mov             r0, r1, lsl #22
	orr		r3, r3, r0
	mov             r0, r1, lsl #14
	orr		r3, r3, r0
	orr		r3, r3, =0x80000000
	ldr		r2, =DDR_SCAL
	str		r3, [r2]

	ldr		r2, [r4]
	cmp		r2, r5
	bne		ddr_loop1
	mov		r6, r1
ddr_loop2:
	add		r1, r1, =0x1
	cmp		r1, =0xf
	ble		end_loop
        mov             r3, r1
        mov             r0, r1, lsl #30
        orr             r3, r3, r0
        mov             r0, r1, lsl #22
        orr             r3, r3, r0
        mov             r0, r1, lsl #14
        orr             r3, r3, r0
        orr             r3, r3, =0x80000000
        ldr             r2, =DDR_SCAL
        str             r3, [r2]

	ldr		r2, [r4]
	cmp		r2, r5
	be		ddr_loop2
	mov		r7, r2

	add		r3, r6, r7
	lsr		r3, r3, =0x1
        mov             r0, r1, lsl #30
        orr             r3, r3, r0
        mov             r0, r1, lsl #22
        orr             r3, r3, r0
        mov             r0, r1, lsl #14
        orr             r3, r3, r0
        orr             r3, r3, =0x80000000
        ldr             r2, =DDR_SCAL

end_loop:
*/
/*	@ Case 3:	Hardware Calibratoin
	ldr             r0, =DDR_HCAL           @ DDR_HCAL
	ldr             r1, =0x803ffc07     @ the offset is correct? -SC
	str             r1, [r0]
	wait		#5
	ldr             r1, [r0]


*/
	mov	pc, lr
